#pragma once

#include <iostream>
#include <fstream>
#include <string>
#include <ctime>
#include <sys/types.h>
#include <unistd.h>
#include <stdarg.h>
#include "LockGuard.hpp"

namespace ns_log
{
    enum Level
    {
        DEBUG = 0, //
        INFO,      // 常规
        WARNING,   // 警告
        ERROR,     // 错误
        FATAL      // 致命
    };

    bool gIsSave = false;                  // 控制是否将日志保存到文件
    const std::string logname = "log.txt"; // 文件名

    // 将日志消息写入文件
    void Save(const std::string &filename, const std::string &message)
    {
        std::ofstream out(filename, std::ios::app);
        if (!out.is_open())
        {
            return;
        }
        out << message;
        out.close();
    }

    // 根据日志级别返回对应的字符串描述
    std::string GetLevel(int level)
    {
        switch (level)
        {
        case Level::DEBUG:
            return "DEBUG";
        case Level::INFO:
            return "INFO";
        case Level::WARNING:
            return "WARNING";
        case Level::ERROR:
            return "ERROR";
        case Level::FATAL:
            return "FATAL";

        default:
            return "Unknown";
        }
    }

    // 获取当前时间的字符串表示形式
    std::string GetTime()
    {
        time_t cur_time = time(nullptr);
        struct tm *format_time = localtime(&cur_time);
        if (format_time == nullptr)
            return "None";
        char time_buff[1024];
        snprintf(time_buff, sizeof(time_buff), "%d-%d-%d %d:%d:%d",
                 format_time->tm_year + 1900, format_time->tm_mon + 1, format_time->tm_mday,
                 format_time->tm_hour, format_time->tm_min, format_time->tm_sec);
        return time_buff;
    }

    pthread_mutex_t gmutex = PTHREAD_MUTEX_INITIALIZER;

    // 根据传入的参数格式化日志消息并输出或保存
    void LogMessage(std::string filename, int line, int level, const char *format, ...)
    {
        std::string levelstr = GetLevel(level);
        std::string timestr = GetTime();
        pid_t selfid = getpid();

        char buffer[1024];

        // 处理可变参数列表
        va_list arg;
        va_start(arg, format);
        vsnprintf(buffer, sizeof(buffer), format, arg);
        va_end(arg);

        std::string message = "[" + timestr + "]" + "[" + levelstr + "]" +
                              "[" + std::to_string(selfid) + "]" +
                              "[" + filename + "]" + "[" + std::to_string(line) + "] " + buffer;

        // 自动管理互斥锁
        LockGuard lockguard(&gmutex);

        if (!gIsSave)
            std::cout << message;
        else
            Save(logname, message);
    }

// 用c99宏的新特性简化日志记录
#define LOG(level, format, ...)                                       \
    do                                                                \
    {                                                                 \
        LogMessage(__FILE__, __LINE__, level, format, ##__VA_ARGS__); \
    } while (0)

#define SaveToFile()    \
    do                  \
    {                   \
        gIsSave = true; \
    } while (0)
#define PrintToScreen()  \
    do                   \
    {                    \
        gIsSave = false; \
    } while (0)
}
